package webjoch.process.strategies.puzzles;

import java.awt.Graphics2D;

import com.rsbuddy.event.events.MessageEvent;
import com.rsbuddy.script.methods.Calculations;
import com.rsbuddy.script.methods.Camera;
import com.rsbuddy.script.methods.Objects;
import com.rsbuddy.script.methods.Players;
import com.rsbuddy.script.task.Task;
import com.rsbuddy.script.util.Filter;
import com.rsbuddy.script.util.Random;
import com.rsbuddy.script.wrappers.GameObject;
import com.rsbuddy.script.wrappers.Tile;

import webjoch.process.strategies.Puzzle;
import webjoch.wrappers.Room;

/**
 * 
 * @author UbserMouse
 *
 */

public class ImbueTiles extends Puzzle{
	Room room;
	
	static final int YELLOW = 49641, GREEN = 49638;

	boolean[][] grid;
    boolean[] imbueTop = null;

	
	@Override
	public void setRoom(Room room) {
		this.room = room;
	}

	@Override
	public boolean isValid() {
		return getGrid() != null;
	}

	@Override
	public Type getType() {
		return Type.IMBUE_TILES;
	}

    @Override
    public int loop(){
        if (!Players.getLocal().isMoving() && Players.getLocal().getAnimation() == -1) {
        	grid = getGrid();
            Tile corner = getCorner();
            System.out.println(corner);
            if (imbueTop != null){
            	System.out.println(imbueTop);
                for (int i = 0; i < 5; i++)
                    if (imbueTop[i]) {
                        GameObject panel = getPanelAt(corner.getX() + i, corner.getY());
                        if (Calculations.distanceTo(panel) < 5) {
                            panel.getLocation().interact("Imbue");
                            waitForFlip();
                            imbueTop[i] = false;
                        }else {
                            Camera.turnTo(panel);
                            return 1000;
                        }
                        return 500;
                    }
                imbueTop = null;
            }else{
                for (int r = 0; r < 4; r++) {
                    for (int c = 0; c < 5; c++) {
                        if (grid[r][c]) {
                        	GameObject panel = getPanelAt(corner.getX() + c, corner.getY() + r + 1);
                        	if (Calculations.distanceTo(panel) < 5){
                        		System.out.println(panel.getId());
                                panel.getLocation().interact("Imbue");
                                waitForFlip();
                            }else{
                            	panel.getLocation().clickOnMap();
                                return 1000;
                            }
                            return 500;
                        }
                    }
                }
                imbueTop = toBoolArr(getCounterpart(toInt(grid[4])));
                System.out.println("imbue top");
            }
        }
        return Random.nextInt(400, 700);
    }

    public void waitForFlip() {
        for (int i = 0; i < 100 && Players.getLocal().getAnimation() == -1; i++) {
            Task.sleep(20);
        }
        for (int i = 0; i < 100 && Players.getLocal().getAnimation() != -1; i++) {
            Task.sleep(20);
        }
        Task.sleep(2000);
    }

    public int toInt(boolean[] row) {
        int ret = 0;
        int[] arr = {0x1, 0x2, 0x4, 0x8, 0x10};
        for (int i = 0; i < row.length; i++)
            if (row[i]) ret += arr[i];
        return ret;
    }

    public int getCounterpart(int i) {
        if (i == bin("10001"))
            return bin("11000");
        if (i == bin("01010"))
            return bin("10010");
        if (i == bin("11100"))
            return bin("01000");
        if (i == bin("00111"))
            return bin("00010");
        if (i == bin("10110"))
            return bin("00001");
        if (i == bin("01101"))
            return bin("10000");
        if (i == bin("11011"))
            return bin("00100");
        return 0;
    }

    public int bin(String s) {
        return Integer.parseInt(s, 2);
    }

    public boolean[] toBoolArr(int num) {
        boolean[] b = new boolean[5];
        int[] arr = {0x1, 0x2, 0x4, 0x8, 0x10};
        for (int i = 0; i < 5; i++) {
            b[i] = ((num & arr[i]) != 0);
        }
        return b;
    }

    public GameObject getPanelAt(int x, int y) {
        return getPanelAt(new Tile(x, y));
    }

    public GameObject getPanelAt(Tile t) {
        for (GameObject o : Objects.getAllAt(t))
            if (o.getId() == YELLOW || o.getId() == GREEN)
                return o;
        return null;
    }

    public Tile getCorner() {
        int x = 0, y = 0;
        GameObject[] tiles = Objects.getLoaded(new Filter<GameObject>(){
            public boolean accept(GameObject o) {
                return room.getArea().contains(o.getLocation()) && (o.getId() == YELLOW || o.getId() == GREEN);
            }
        });
        for (GameObject o : tiles) {
            if (x == 0 || o.getLocation().getX() < x)
                x = o.getLocation().getX();
            if (y == 0 || o.getLocation().getY() < y)
                y = o.getLocation().getY();
        }
        return new Tile(x, y);
    }

    public boolean[][] getGrid() {
        boolean[][] g = new boolean[5][5];
        GameObject[] panels = Objects.getLoaded(new Filter<GameObject>()
        {
            public boolean accept(GameObject o) {
                return room.getArea().contains(o.getLocation()) && (o.getId() == YELLOW || o.getId() == GREEN);
            }
        });
        if (panels.length == 0) return null;
        Tile corner = getCorner();
        int x = corner.getX(), y = corner.getY();
        for (GameObject o : panels) {
            if (o.getLocation().getX() - x < 5 && o.getLocation().getY() - y < 5
                && o.getLocation().getX() - x >= 0 && o.getLocation().getY() - y >= 0)
                g[o.getLocation().getY() - y][o.getLocation().getX() - x] = (o.getId() == GREEN);
        }
        return g;
    }

	@Override
	public int[] itemNeed() {
		return new int[0];
	}

	@Override
	public boolean isFinished(){
		if (grid == null) return false;
		boolean fill = grid[0][0];
        for (boolean[] bool : grid)
            for (boolean b : bool)
                if (b != fill)
                    return false;
        return true;
	}

	@Override
	public void messageReceived(MessageEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onRepaint(Graphics2D g) {
		// TODO Auto-generated method stub
		
	}

}
